package com.itheima.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MapperUtil {

    //直接获取batis代理对象
    public static <T> T  getMapper(Class<T> aClass){
        final SqlSession session = getSession();

        //1、创建目标对象
        final T mapper = session.getMapper(aClass);

        //2、创建代理对象
        /*
        * JDK动态代理：
         *   涉及的类：Proxy
         *   创建代理对象的方法：newProxyInstance(param1,param2,param3)]
         *   三个参数：
         *          param1:指定目标对象的类的加载器(固定写法)
         *          param2:获取目标对象可能实现的所有接口(固定写法)
         *          param3:代理处理实现，需要手动实现
        */
        T tProxy = (T)Proxy.newProxyInstance(mapper.getClass().getClassLoader(), mapper.getClass().getInterfaces(), new InvocationHandler() {
            /**
             * @param proxy   代理对象
             * @param method  执行目标对象上的方法对象
             * @param args    执行目标方法的参数列表
             * @return 执行目标方法的返回值
             * @throws Throwable
             */
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object obj = null;
                try {
                    obj = method.invoke(mapper, args);
                } catch (Exception e) {
                    System.out.println(e);
                } finally {
                    if (session != null) {
                        session.commit();
                        session.close();
                    }
                }
                return obj;
            }
        });
        return tProxy;

    }

    public static SqlSession getSession() {
        SqlSession session = null;
        try {
            InputStream is = Resources.getResourceAsStream("sql.xml");
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            session = factory.openSession();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return session;
    }

    public static void close(SqlSession session){
        if(session!=null){
            session.commit();
            session.close();
        }
    }
}
